From: Boris Ostrovsky Date: Tue, 3 Feb 2015 10:30:40 +0000 (+0100) Subject: x86/VPMU: handle APIC_LVTPC accesses X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~3799 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22?a=commitdiff_plain;h=24fdc89e48b737d5131863621df56cb76914ffba;p=xen.git x86/VPMU: handle APIC_LVTPC accesses Don't have the hypervisor update APIC_LVTPC when _it_ thinks the vector should be updated. Instead, handle guest's APIC_LVTPC accesses and write what the guest explicitly wanted (but only when VPMU is enabled). This is updated version of commit 8097616fbdda that was reverted by cc3404093c85. Unlike the previous version, we don't update APIC_LVTPC when VPMU is disabled to avoid interfering with NMI watchdog (which runs only when VPMU is off). Signed-off-by: Boris Ostrovsky Acked-by: Kevin Tian --- diff --git a/xen/arch/x86/hvm/svm/vpmu.c b/xen/arch/x86/hvm/svm/vpmu.c index 19777e3aa5..64dc1678f1 100644 --- a/xen/arch/x86/hvm/svm/vpmu.c +++ b/xen/arch/x86/hvm/svm/vpmu.c @@ -302,8 +302,6 @@ static int amd_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content, if ( !acquire_pmu_ownership(PMU_OWNER_HVM) ) return 1; vpmu_set(vpmu, VPMU_RUNNING); - apic_write(APIC_LVTPC, PMU_APIC_VECTOR); - vpmu->hw_lapic_lvtpc = PMU_APIC_VECTOR; if ( has_hvm_container_vcpu(v) && !((struct amd_vpmu_context *)vpmu->context)->msr_bitmap_set ) @@ -314,8 +312,6 @@ static int amd_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content, if ( (get_pmu_reg_type(msr) == MSR_TYPE_CTRL) && (is_pmu_enabled(msr_content) == 0) && vpmu_is_set(vpmu, VPMU_RUNNING) ) { - apic_write(APIC_LVTPC, PMU_APIC_VECTOR | APIC_LVT_MASKED); - vpmu->hw_lapic_lvtpc = PMU_APIC_VECTOR | APIC_LVT_MASKED; vpmu_reset(vpmu, VPMU_RUNNING); if ( has_hvm_container_vcpu(v) && ((struct amd_vpmu_context *)vpmu->context)->msr_bitmap_set ) diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index 8062f315b4..5da6d8fa98 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -777,6 +778,8 @@ static int vlapic_reg_write(struct vcpu *v, } if ( (offset == APIC_LVTT) && !(val & APIC_LVT_MASKED) ) pt_may_unmask_irq(NULL, &vlapic->pt); + if ( offset == APIC_LVTPC ) + vpmu_lvtpc_update(val); break; case APIC_TMICT: diff --git a/xen/arch/x86/hvm/vmx/vpmu_core2.c b/xen/arch/x86/hvm/vmx/vpmu_core2.c index 4d0e9a80b2..77931452e6 100644 --- a/xen/arch/x86/hvm/vmx/vpmu_core2.c +++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c @@ -519,19 +519,6 @@ static int core2_vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content, else vpmu_reset(vpmu, VPMU_RUNNING); - /* Setup LVTPC in local apic */ - if ( vpmu_is_set(vpmu, VPMU_RUNNING) && - is_vlapic_lvtpc_enabled(vcpu_vlapic(v)) ) - { - apic_write_around(APIC_LVTPC, PMU_APIC_VECTOR); - vpmu->hw_lapic_lvtpc = PMU_APIC_VECTOR; - } - else - { - apic_write_around(APIC_LVTPC, PMU_APIC_VECTOR | APIC_LVT_MASKED); - vpmu->hw_lapic_lvtpc = PMU_APIC_VECTOR | APIC_LVT_MASKED; - } - if ( type != MSR_TYPE_GLOBAL ) { u64 mask; @@ -697,10 +684,6 @@ static int core2_vpmu_do_interrupt(struct cpu_user_regs *regs) return 0; } - /* HW sets the MASK bit when performance counter interrupt occurs*/ - vpmu->hw_lapic_lvtpc = apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED; - apic_write_around(APIC_LVTPC, vpmu->hw_lapic_lvtpc); - return 1; } diff --git a/xen/arch/x86/hvm/vpmu.c b/xen/arch/x86/hvm/vpmu.c index b2e8e652a5..0e6b6c022b 100644 --- a/xen/arch/x86/hvm/vpmu.c +++ b/xen/arch/x86/hvm/vpmu.c @@ -65,6 +65,19 @@ static void __init parse_vpmu_param(char *s) } } +void vpmu_lvtpc_update(uint32_t val) +{ + struct vpmu_struct *vpmu; + + if ( !opt_vpmu_enabled ) + return; + + vpmu = vcpu_vpmu(current); + + vpmu->hw_lapic_lvtpc = PMU_APIC_VECTOR | (val & APIC_LVT_MASKED); + apic_write(APIC_LVTPC, vpmu->hw_lapic_lvtpc); +} + int vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content, uint64_t supported) { struct vpmu_struct *vpmu = vcpu_vpmu(current); diff --git a/xen/include/asm-x86/hvm/vpmu.h b/xen/include/asm-x86/hvm/vpmu.h index ddc2748498..9c4e65aae0 100644 --- a/xen/include/asm-x86/hvm/vpmu.h +++ b/xen/include/asm-x86/hvm/vpmu.h @@ -104,6 +104,7 @@ static inline bool_t vpmu_are_all_set(const struct vpmu_struct *vpmu, return !!((vpmu->flags & mask) == mask); } +void vpmu_lvtpc_update(uint32_t val); int vpmu_do_wrmsr(unsigned int msr, uint64_t msr_content, uint64_t supported); int vpmu_do_rdmsr(unsigned int msr, uint64_t *msr_content); void vpmu_do_interrupt(struct cpu_user_regs *regs);